(ns metabase.xrays.transforms.materialize
  (:require
   [metabase.api.common :as api]
   [metabase.collections.models.collection :as collection]
   [metabase.lib-be.core :as lib-be]
   [metabase.lib.schema.id :as lib.schema.id]
   [metabase.queries.core :as queries]
   [metabase.queries.schema :as queries.schema]
   [metabase.query-processor.preprocess :as qp.preprocess]
   [metabase.util.malli :as mu]
   [metabase.xrays.transforms.specs :as transforms.specs]
   [toucan2.core :as t2]))

(declare get-or-create-root-container-collection!)

(defn- root-container-location
  []
  (collection/children-location
   (t2/select-one [:model/Collection :location :id]
                  :id (get-or-create-root-container-collection!))))

(mu/defn get-collection :- [:maybe ::lib.schema.id/collection]
  "Get collection named `collection-name`. If no location is given root collection for automatically
   generated transforms is assumed (see `get-or-create-root-container-collection!`)."
  ([collection-name]
   (get-collection collection-name (root-container-location)))
  ([collection-name :- :string
    location        :- :string]
   (t2/select-one-pk :model/Collection
                     :name     collection-name
                     :location location)))

(defn- create-collection!
  ([collection-name description]
   (create-collection! collection-name description (root-container-location)))
  ([collection-name description location]
   (first (t2/insert-returning-pks! :model/Collection
                                    {:name        collection-name
                                     :description description
                                     :location    location}))))

(defn- get-or-create-root-container-collection!
  "Get or create container collection for transforms in the root collection."
  []
  (let [location "/"
        name     "Automatically Generated Transforms"]
    (or (get-collection name location)
        (create-collection! name nil location))))

(defn fresh-collection-for-transform!
  "Create a new collection for all the artefacts belonging to transform, or reset it if it already
   exists."
  [{:keys [name description]}]
  (if-let [collection-id (get-collection name)]
    (t2/delete! :model/Card :collection_id collection-id)
    (create-collection! name description)))

(mu/defn make-card-for-step! :- ::queries.schema/card
  "Make and save a card for a given transform step and query."
  [{:keys [name transform description]} :- transforms.specs/Step
   query                                :- ::transforms.specs/query]
  (let [query (lib-be/normalize-query query)]
    (->> {:creator_id             api/*current-user-id*
          :dataset_query          query
          :description            description
          :name                   name
          :collection_id          (get-collection transform)
          :result_metadata        (qp.preprocess/query->expected-cols query)
          :visualization_settings {}
          :display                :table}
         queries/populate-card-query-fields
         (t2/insert-returning-instances! :model/Card)
         first)))
